import LikeDislikeSongCommand = require("commands/likeDislikeSongCommand");

class Song {

    static unranked: number = 0;
    static liked: number = 1;
    static disliked: number = 2;

    name: string;
    album: string;
    artist: string;
    albumArtUri: string;
    albumSongNumber: number;
    uri: string;
    likeStatus: KnockoutObservable<number>;
    communityRank: KnockoutObservable<number>;
    id: string;
    isLiked: KnockoutComputed<boolean>;
    isDisliked: KnockoutComputed<boolean>;
    thumbUpImage: KnockoutComputed<string>;
    thumbDownImage: KnockoutComputed<string>;
    communityRankColor: KnockoutComputed<string>;
    likeHoverText: KnockoutComputed<string>;
    dislikeHoverText: KnockoutComputed<string>;
    lyrics: string;
    genres = ko.observableArray<string>();

    constructor(dto: SongDto) {
        this.name = dto.Name;
        this.albumSongNumber = dto.Number;
        this.album = dto.Album;
        this.artist = dto.Artist;
        this.albumArtUri = dto.AlbumArtUri;
        this.uri = dto.Uri;
        this.likeStatus = ko.observable(dto.SongLike);
        this.communityRank = ko.observable(dto.CommunityRank);
        this.id = dto.Id;
        this.lyrics = dto.Lyrics;
        this.genres(dto.Genres);

        this.isLiked = ko.computed(() => this.likeStatus() === Song.liked);
        this.isDisliked = ko.computed(() => this.likeStatus() === Song.disliked);
        this.thumbUpImage = ko.computed(() => "/content/images/up" + (this.isLiked() ? "Checked.png" : ".png"));
        this.thumbDownImage = ko.computed(() => "/content/images/down" + (this.isDisliked() ? "Checked.png" : ".png"));
        this.likeHoverText = ko.computed(() => this.likeStatus() === Song.liked ? "You've already liked this song. We'll keep playing more songs like it" : "I like this song, play more songs like it");
        this.dislikeHoverText = ko.computed(() => this.likeStatus() === Song.disliked ? "You already disliked this song. We'll keep it on the back shelf, and rarely play it for you" : "I don't like this song, don't play it again");
    }

    play() {
        // Play by ID causes fetch to the server to get the song.
        // That fetch is necessary to grab information like the like status of a song.
        ko.postbox.publish("PlaySongById", { songId: this.id });
    }

    playSongFromArtist() {
        ko.postbox.publish("Pause");
        ko.postbox.publish("GET", {
            url: "/API/Songs/GetSongByArtist",
            data: { artist: this.artist },
            responseMessage: "SongFetched"
        });
    }

    playSongFromAlbum() {
        ko.postbox.publish("Pause");
        ko.postbox.publish("GET", {
            url: "/API/Songs/GetSongByAlbum",
            data: { album: this.album },
            responseMessage: "SongFetched"
        });
    }

    dislike() {
        if (!this.isDisliked()) {
            var incrementAmount = this.isLiked() ? -2 : -1;
            this.likeOrDislike(incrementAmount, "Dislike");
            ko.postbox.publish("NextSong");
        }
    }

    like() {
        if (!this.isLiked()) {
            var incrementAmount = this.isDisliked() ? 2 : 1;
            this.likeOrDislike(incrementAmount, "Like");
        }
    }

    likeOrDislike(increment, actionName) {
        this.communityRank(this.communityRank() + increment);
        this.likeStatus(increment > 0 ? Song.liked : Song.disliked);

        new LikeDislikeSongCommand(this.id, increment > 0)
            .execute()
            .done((rating: number) => this.communityRank(rating));
    }
} 

export = Song;